﻿#ifndef __DEF_H__
#define __DEF_H__

#define DEC_1 0
#define DEC_2 1
#define DEC_3 2
#define DEC_4 3
#define DEC_5 4
#define DEC_6 5
#define DEC_7 6
#define DEC_8 7
#define DEC_9 8
#define DEC_10 9
#define DEC_11 10
#define DEC_12 11
#define DEC_13 12
#define DEC_14 13
#define DEC_15 14
#define DEC_16 15
#define DEC_17 16
#define DEC_18 17
#define DEC_19 18
#define DEC_20 19
#define DEC_21 20
#define DEC_22 21
#define DEC_23 22
#define DEC_24 23
#define DEC_25 24
#define DEC_26 25
#define DEC_27 26
#define DEC_28 27
#define DEC_29 28
#define DEC_30 29

#define DEC(n) DEC_##n

#define XY(x,y) x##y
#define APPEND(x,y) XY(x,y)

#define REPEAT_0(p,n)
#define REPEAT_1(p,n) APPEND(p,_FIRST)
#define REPEAT_2(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_3(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_4(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_5(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_6(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_7(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_8(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_9(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_10(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_11(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_12(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_13(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_14(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_15(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_16(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_17(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_18(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_19(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_20(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_21(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_22(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_23(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_24(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_25(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_26(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_27(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_28(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_29(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))
#define REPEAT_30(p,n) APPEND(APPEND(REPEAT_,DEC(n))(p,DEC(n)),p(n))

//typename P1, typename P2 ...
#define TYPE_PARAM_FIRST typename P1
#define TYPE_PARAM(n) ,typename P##n
#define TYPE_PARAMS(n) APPEND(REPEAT_,n)(TYPE_PARAM,n)

//P1, P2 ...
#define PARAM_FIRST P1
#define PARAM(n) ,P##n
#define PARAMS(n) APPEND(REPEAT_,n)(PARAM,n)

//P1 p1, P2 p2 ...
#define DEF_ARG_FIRST P1& p1
#define DEF_ARG(n) ,P##n& p##n
#define DEF_ARGS(n) APPEND(REPEAT_,n)(DEF_ARG,n)

//p1, p2 ...
#define VAR_FIRST p1
#define VAR(n) ,p##n
#define VARS(n) APPEND(REPEAT_,n)(VAR,n)

#define COMMA_TYPE_PARAM_FIRST ,typename P1
#define COMMA_TYPE_PARAM(n) ,typename P##n
#define COMMA_TYPE_PARAMS(n) APPEND(REPEAT_,n)(COMMA_TYPE_PARAM,n)

#define COMMA_PARAM_FIRST ,P1
#define COMMA_PARAM(n) ,P##n
#define COMMA_PARAMS(n) APPEND(REPEAT_,n)(COMMA_PARAM,n)

#define COMMA_VAR_FIRST ,p1
#define COMMA_VAR(n) ,p##n
#define COMMA_VARS(n) APPEND(REPEAT_,n)(COMMA_VAR,n)

#define FUNCTION_REPEAT30(p,v,c)\
    p(0,v,c)\
    p(1,v,c)\
    p(2,v,c)\
    p(3,v,c)\
    p(4,v,c)\
    p(5,v,c)\
    p(6,v,c)\
    p(7,v,c)\
    p(8,v,c)\
    p(9,v,c)\
    p(10,v,c)\
    p(11,v,c)\
    p(12,v,c)\
    p(13,v,c)\
    p(14,v,c)\
    p(15,v,c)\
    p(16,v,c)\
    p(17,v,c)\
    p(18,v,c)\
    p(19,v,c)\
    p(20,v,c)\
    p(21,v,c)\
    p(22,v,c)\
    p(23,v,c)\
    p(24,v,c)\
    p(25,v,c)\
    p(26,v,c)\
    p(27,v,c)\
    p(28,v,c)\
    p(29,v,c)\
    p(30,v,c)

#endif